/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年9月4日
 */
package com.massyframework.beanskin.runtime.nativelib;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

import com.massyframework.beanskin.ParseException;
import com.massyframework.beanskin.framework.Framework;

/**
 * @author huangkh
 *
 */
public abstract class XmlParser {

	private Validator validator;
	
	/**
	 * 
	 */
	public XmlParser() {
	}

	/**
     * 获取节点的TextContent数据
     * @param node 节点
     * @return {@link String}, 可以返回null.
     */
    public String getTextContent(Node node){
        if (node == null) return null;

        String result = node.getTextContent();
        if (result == null){
            return null;
        }

        result = StringUtils.trim(result);
        if (result.isEmpty()){
            return null;
        }

        return result;
    }
    
    /**
     * 验证 xml文件的有效性
     * @param xmlFile {@link File}, xml文件
     * @throws SAXException xml解析发生例外
     * @throws IOException io读写发生例外
     */
    protected void validateXml(File xmlFile) throws SAXException, IOException{
        InputStream inputStream = null;
        try{
            inputStream = new FileInputStream(xmlFile);
            StreamSource source = new StreamSource(inputStream);
            this.getValidator().validate(source);
        }finally{
            if (inputStream != null) {
                try {
                    inputStream.close();
                }catch(IOException e) {

                }
            }
        }
    }
    
    /**
     * 创建Xml Document对象
     * @param inputStream 输入流
     * @return {@link Document}
     * @throws ParseException 解析发生错误抛出的异常
     * @throws IOException IO读写发生异常抛出的异常
     * @throws SAXException SAX解析发生错误抛出的异常
     */
    protected final Document createDocument(InputStream inputStream)
            throws ParseException, IOException {
        try{
            DocumentBuilderFactory factory= DocumentBuilderFactory.newInstance();
            DocumentBuilder builder=factory.newDocumentBuilder();
            return builder.parse(inputStream);
        }catch(ParserConfigurationException e){
            throw new ParseException("load assmebly configuration file failed.", e);
        }catch(SAXException e){
            throw new ParseException("load assmebly configuration file failed.", e);
        }catch(IOException e){
            throw e;
        }
    }

	/**
     * 创建验证器
     * @param xsdResource {@link String},验证所使用的xsd文件路经
     * @return {@link Validator}
     * @throws SAXException
     */
    protected Validator getValidator() throws SAXException {
    	if (this.validator == null) {
	    	ClassLoader loader = Framework.class.getClassLoader();
	    	
	    	String resourceName = this.getResouceNameWithXmlSchemaFile();
	    	URL url =  loader.getResource(resourceName);
	    	if (url == null) {
	    		throw new RuntimeException("cannot found xsd resource:".concat(resourceName).concat("."));
	    	}
	    	
	        SchemaFactory schemaFactory =
	                SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
	
	        Schema schema = schemaFactory.newSchema(url);
	        this.validator = schema.newValidator();
    	}
    	
    	return this.validator;
    }
    
    /**
	 * xml Schema文件路径
	 * @return {@link String}
	 */
	protected abstract String getResouceNameWithXmlSchemaFile();
}
